exports.count = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var now = new Date();
    var nowDays = now.getDays();
    var zeroTime = now.zeroTime().getStamp();

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }

        var dbUser = db.collection('user');
        var dbPlat = db.collection('plat');
        var counts = {};
        var loader = new common.Loader(function() {
            resp.data.push([sid, counts.total, counts.active, counts.create, counts.roll, counts.valid, counts.cost, counts.pay]);
            cb();
        });

        loader.addLoad('total');
        loader.addLoad('active');
        loader.addLoad('create');
        loader.addLoad('roll');
        loader.addLoad('valid');
        loader.addLoad('cost');
        loader.addLoad('pay');

        dbUser.count({}, function(err, count) {
            counts.total = count;
            loader.onLoad('total');
        });

        var today = common.getDate();
        dbUser.count({'mark.day':today}, function(err, count){
            counts.active = count;
            loader.onLoad('active');
        });
        
        var now = new Date();
        var time = Math.round((+new Date(now.getFullYear(), now.getMonth(), now.getDate()))/1000);
        dbPlat.count({'time':{$gt:zeroTime}}, function(err, count) {
            counts.create = count;
            loader.onLoad('create');
        });

        dbUser.count({'info.roll':1}, function(err, count) {
            counts.roll = count;
            loader.onLoad('roll');
        });

        dbUser.count({'mark.tutorial':0}, function(err, count) {
            counts.valid = count;
            loader.onLoad('valid');
        });

        dbUser.count({'daily_vars':{$exists:true}, 'daily_vars.day':nowDays, 'daily_vars.cost_cash':{'$gt':0}}, function(err, count) {
            counts.cost = count;
            loader.onLoad('cost');
        });

        dbUser.count({'daily_vars':{$exists:true}, 'daily_vars.day':nowDays, 'daily_vars.pay_cash':{'$gt':0}}, function(err, count) {
            counts.pay = count;
            loader.onLoad('pay');
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.via = function(query, resp, callback) {
    if (isNaN(query.minTime) || isNaN(query.maxTime)) {
        resp.code = 1; resp.desc = 'invalid params'; 
        callback(); return;
    }

    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var minTime = +query.minTime;
    var maxTime = +query.maxTime;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
    
        var dbUser = db.collection('user');

		var keyf = function(doc){
            var dateTime = new Date(doc.info.create*1000);
            var time = Math.floor((new Date(dateTime.getFullYear(), dateTime.getMonth(),
                dateTime.getDate())).getTime() / 1000);
			var via = doc.info.via || 'default';
			var valid = doc.mark.tutorial ? 0 : 1;
			return {"time": time, 'via':via , 'valid':valid};
		};
        
        var condition = {'info.create':{'$gte':minTime, '$lte':maxTime}};
		var reduce = function(doc,prev){
			++prev.num;
		};

		dbUser.group(keyf, condition, {"num":0}, reduce, function(err,results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

			results.forEach(function(item){
				resp.data.push([sid, item.time, item.via, item.valid, item.num]);
			});
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.viaOneday = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
    
        var dbUser = db.collection('user');
	
		var keyf = function(doc){
            var time = Math.floor(doc.info.create/600);
			var via = doc.info.via || 'default';
			var valid = doc.mark.tutorial ? 0 : 1;
			return {"time": time, 'via':via , 'valid':valid};
		};
        
        var startTime = Date.getStamp() - 86400;
        var condition = {'info.create': {'$gt':startTime}};
		var reduce = function(doc,prev){
			++prev.num;
		};

		dbUser.group(keyf, condition, {"num":0}, reduce, function(err,results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

			results.forEach(function(item){
				resp.data.push([sid, item.time*600, item.via, item.valid, item.num]);
			});
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.level = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
    
        var dbUser = db.collection('user');
        dbUser.group({'status.level':1}, {}, {sum:0}, "function(obj,prev){prev.sum += 1;}", function(err, results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

            results.forEach(function(value){
                resp.data.push([sid, value['status.level'], value.sum]);
            });
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.vip = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }

        var dbUser = db.collection('user');
        dbUser.group({'status.vip':1}, {}, {sum:0}, "function(obj,prev){prev.sum += 1;}", function(err, results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }
            results.forEach(function(value){
                resp.data.push([sid, value['status.vip'], value.sum]);
            });
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.levelVip = function(query, resp, callback) {
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }

        var dbUser = db.collection('user');
        dbUser.group({'status.level':1, 'status.vip':1}, {}, {sum:0}, "function(obj,prev){prev.sum += 1;}", function(err, results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

            results.forEach(function(value){
                resp.data.push([sid, value['status.level'], value['status.vip'], value.sum]);
            });
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.remain = function(query, resp, callback) {
    if (isNaN(query.minTime) || isNaN(query.maxTime)) {
        resp.code = 1; resp.desc = 'invalid params'; 
        callback(); return;
    }

    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var minTime = +query.minTime;
    var maxTime = +query.maxTime;
    var roll = +query.roll || 0;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
		
        var dbUser = db.collection('user');
		var keyf = null;
        if (roll) {
            keyf = function(doc){
                var createTime = new Date(doc.info.create*1000);
                createTime = Math.floor((+new Date(createTime.getFullYear(), createTime.getMonth(), createTime.getDate()))/1000);
                var roll = doc.info.roll||0;
			    return {"create": createTime, "roll":roll};
		    };
        } else {
            keyf = function(doc){
                var createTime = new Date(doc.info.create*1000);
                var createTime = Math.floor((+new Date(createTime.getFullYear(), createTime.getMonth(), createTime.getDate()))/1000);
			    return {"create": createTime};
		    };
        }
        
        var condition = {'info.create':{'$gte':minTime, '$lt':maxTime}};
        var init = {'0':0, '1':0, '3':0, '7':0, '14':0, '30':0, '60':0};
		var reduce = function(doc, prev){
            var dayDiff = 0;
            var loginTime = doc.mark.day;
            if (loginTime) {
                var createTime = prev.create;
                var loginYear = Math.floor(loginTime/10000);
                var loginMonth = Math.floor(loginTime%10000/100) - 1;
                var loginDate = loginTime%100;
                loginTime = Math.floor((+new Date(loginYear, loginMonth, loginDate))/1000);
                dayDiff = Math.floor((loginTime - createTime)/86400);
            }
            
            if (dayDiff >= 60) {
                prev[1]++;
                prev[3]++;
                prev[7]++;
                prev[14]++;
                prev[30]++;
                prev[60]++;
            } else if (dayDiff >= 30) {
                prev[1]++;
                prev[3]++;
                prev[7]++;
                prev[14]++;
                prev[30]++;
            } else if (dayDiff >= 14) {
                prev[1]++;
                prev[3]++;
                prev[7]++;
                prev[14]++;
            } else if (dayDiff >= 7) {
                prev[1]++;
                prev[3]++;
                prev[7]++;
            } else if (dayDiff >= 3) {
                prev[1]++;
                prev[3]++;
            } else if (dayDiff >= 1) {
                prev[1]++;
            }

            prev[0]++;
		};

		dbUser.group(keyf, condition, init, reduce, function(err,results) {
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }

			results.forEach(function(item){
                var remainItem = [sid, item.create, item.roll||0, item[0], item[1], item[3], item[7], item[14], item[30], item[60]];
                resp.data.push(remainItem);
			});
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.remainDay = function(query, resp, callback) {
    if (isNaN(query.minTime) || isNaN(query.maxTime) || isNaN(query.day)) {
        resp.code = 1; resp.desc = 'invalid params'; 
        callback(); return;
    }
    
    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var minTime = +query.minTime;
    var maxTime = +query.maxTime;
    var day = +query.day;
    var roll = +query.roll || 0;

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
		
        var dbUser = db.collection('user');
		var keyf = null;
        if (roll) {
            keyf = function(doc){
                var createTime = new Date(doc.info.create*1000);
                var createTime = Math.floor((+new Date(createTime.getFullYear(), createTime.getMonth(), createTime.getDate()))/1000);
                var roll = doc.info.roll||0;
			    return {"create": createTime, "roll":roll};
		    };
        } else {
            keyf = function(doc){
                var createTime = new Date(doc.info.create*1000);
                var createTime = Math.floor((+new Date(createTime.getFullYear(), createTime.getMonth(), createTime.getDate()))/1000);
			    return {"create": createTime};
		    };
        }
        
        var condition = {'info.create':{'$gte':minTime, '$lt':maxTime}};
        var init = {'day': day};
        for (var i = 0; i <= init.day; ++i) {
            init[i] = 0; 
        }
		var reduce = function(doc, prev){
            var dayDiff = 0;
            var loginTime = doc.mark.day;
            if (loginTime) {
                var createTime = prev.create;
                var loginYear = Math.floor(loginTime/10000);
                var loginMonth = Math.floor(loginTime%10000/100) - 1;
                var loginDate = loginTime%100;
                loginTime = Math.floor((+new Date(loginYear, loginMonth, loginDate))/1000);
                dayDiff = Math.floor((loginTime - createTime)/86400);
                if (dayDiff > prev.day) {
                    dayDiff = prev.day;
                }
            }

            for (var i = 1; i <= dayDiff; ++i) {
                prev[i]++;
            }

            prev[0]++;
		};

		dbUser.group(keyf, condition, init, reduce, function(err,results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }
            
			results.forEach(function(item){
                var remainItem = [sid, item.create, item.roll||0];
                for (var i = 0; i <= item.day; ++i) {
                    remainItem.push(item[i]);
                }
                resp.data.push(remainItem);
			});
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.lose = function(query, resp, callback) {
    if (isNaN(query.day)) {
        resp.code = 1; resp.desc = 'invalid params'; 
        callback(); return;
    }

    var minSid = +query.minSid;
    var maxSid = +query.maxSid;
    var day = +query.day;
    var minDay = (new Date.createFromStamp(Date.getStamp() - day*86400)).zeroTime().getDateNumber();

    async.each(gServers.getSids(minSid, maxSid), function(sid, cb) {
        var db = gServers.getGameDB(sid);
        if (!db) {
            cb(); return;
        }
		
        var dbUser = db.collection('user');
        var condition = {'mark.day':{'$lt':minDay}};
		var reduce = function(doc, prev) {
            prev.num++;
		};

		dbUser.group({'status.level':1}, condition, {'num':0}, reduce, function(err,results){
            if (err || !results) {
                cb(util.format('server %d db error', sid)); return;
            }
            
			results.forEach(function(item){
                resp.data.push([sid, item['status.level'], item.num]);
			});
            cb();
        });
    }, function(err) {
        if (err) {
            resp.code = 1; resp.desc = err;
        }
        callback();
    });
}

exports.league = function(query, resp, callback){
    if (isNaN(query.sid)) {
        resp.code = 1; resp.desc = 'invalid params';
        callback(); return;
    }

    var sid = +query.sid;
    var uid = +query.uid;
    var name = query.name;

    if (isNaN(uid) && !name) {
        resp.code = 1; resp.desc = 'invalid params';
        callback(); return;
    }

    var db = gServers.getGameDB(sid);
    if (!db) {
        resp.code = 1; resp.desc = 'not db found for this sid';
        callback(); return;
    }

    var league;
    var ret = [];

    async.series([
        function(cb) {
            // 如果提供的是UID，查询军团名字
            if (!isNaN(uid) && uid > 0) {
                db.collection("user").findOne({_id : uid}, {}, function(err, doc){
                    if (err || !doc) {
                        cb('not db found for this uid');
                    } else {
                        name = doc.league.name;
                        cb(null);
                    }
                });
            } else
                cb(null);
        },

        function(cb) {
            // 查找军团
            db.collection("world").findOne({_id : 'league'}, {}, function(err, doc){
                if (err || !doc) {
                    cb('db err');
                } else {
                    league = doc.league[name];
                    if (!league) {
                        cb('no league found of name ' + name);
                    } else {
                        cb(null);
                    }
                }
            });
        },

        function(cb) {
            async.each(Object.keys(league.members), function(muid, ecb) {
                queryUser(+muid, function(err, res){
                    if (res) {
                        var post = "团员";
                        if (league.leader == muid) {
                            post = "团长";
                        } else if (league.vice_leader.indexOf(muid) != -1) {
                            post = "副团长";
                        }
                        res.push(post);
                        ret.push(res);
                    }
                    ecb(null);
                });
            }, function(err){
                cb(null);
            });
        }
    ], function(err){
        if (err) {
            resp.code = 1; resp.desc = err;
        } else {
            resp.data = ret;
        }

        callback && callback();
    });

    function queryUser(quid, fn){

        var userOpenid = "unk";
        var rank = 0;

        async.series([
            function(cb){
                // 查询玩家OPENID
                db.collection("plat").find({}).toArray(function(err, res){
                    if (!err && res) {
                        res.forEach(function(item){
                            if ((item.uid == quid)
                                || (item.uids && (item.uids.indexOf(quid) != -1))) {
                                userOpenid = item._id;
                            }
                        });
                    }
                    cb(null);
                });
            },

            function(cb) {
                // 查询擂台排名
                db.collection("world").findOne({_id : 'rank'}, {}, function(err, doc){
                    if (!err && doc) {
                        for (var _rank in doc.rank) {
                            if (doc.rank[_rank] == quid) {
                                rank = _rank;
                                break;
                            }
                        }
                    }
                    cb(null);
                });
            }
        ], function(err){
            // 角色相关数据
            db.collection("user").findOne({_id : quid}, {}, function(err, doc){
                if (err || !doc) {
                    fn('not user found for this uid ' + quid);
                } else {
                    fn(null, [
                        userOpenid,                 // OPENID
                        quid,                       // UID
                        doc.info.un,                // 名称
                        doc.status.level,           // 等级
                        +rank,                       // 擂台排名
                        doc.league.contribute       // 军团贡献
                    ]);
                }
            });
        });
    }
};